package cn.com.yangzhenyu.Singleton;

/**
 * 饱汉式 用到再实例化 双重检查 保证效率和线程安全的可靠性
 * 双重检查，指的是两次检查 instance 是否为 null。
 * volatile 在这里是需要的。
 * 很多人不知道怎么写，直接就在 getInstance() 方法签名上加上 synchronized，这就不多说了，性能太差。
 * Created By 杨振宇
 * Date: 2020/12/6
 * Time: 20:11
 */
public class Singleton2 {
    // 首先，也是先堵死 new Singleton() 这条路
    private Singleton2() {}
    // 和饿汉模式相比，这边不需要先实例化出来，注意这里的 volatile，它是必须的
    // volatile 立即生效
    // 声明变量是 volatile 的，JVM 保证了每次读变量都从内存中读，跳过 CPU cache 这一步。
    // volatile 的读性能消耗与普通变量几乎相同，但是写操作稍慢，因为它需要在本地代码中插入许多内存屏障指令来保证处理器不发生乱序执行。
    private static volatile Singleton2 instance = null;

    public static Singleton2 getInstance() {
        if (instance == null) {
            // 加锁
            synchronized (Singleton2.class) {
                // 这一次判断也是必须的，不然会有并发问题
                if (instance == null) {
                    instance = new Singleton2();
                }
            }
        }
        return instance;
    }
}
